iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 30
0
自我挑戰組

今晚我想來點 Ruby on Rails 系列 第 30

<Day 30>如何使用 scope

  • 分享至 

  • xImage
  •  

什麼是 scope ,為什麼好用?in Rails & why is it useful?

Scopes 都是定義在 rails models 裡面客制的詢問。每個 scope 接受兩個參數:

一個名稱,用來呼叫這個 scope
一個 lambda,用來完成這個詢問,像這樣:

class Fruit < ApplicationRecord
  scope :with_juice, -> { where("juice > 0") }
end

如同呼叫一個 scope 的結果,會得到一個 ActiveRecord::Relation 物件。另外一個意思是說可以串接&結合 scopes!

例如:

Fruit.with_juice.with_round_shape.first(3)

何時使用 Scopes?

先看個範例

def index
  @books = Book.where("LENGTH(title) > 20")
end

這是一個 index controller action ,用來顯示超過20個字母的書名。如果想要其他地方使用這個詢問,就必須重複這段程式碼。重複的程式碼讓整個專案難以維護,那就把這個詢問移到一個 scope。像這樣:

class Book
  scope :with_long_title, -> { where("LENGTH(title) > 20") }
end

現在 controller action 看起來像這樣:

def index
  @books = Book.with_long_title
end

如何使用帶有參數的 Scopes

當想要把變數放到 scope ,在使用上有更多彈性。像這樣:

class Book
  scope :with_long_title, ->(length) { where("LENGTH(title) > ?", length) }
end

這個 “?” 符號是一個 placeholder,會被後面的“length”值替換掉,讓程式碼更安全。如果要設定一個預設值:

class Book
  scope :with_long_title, ->(length = 20) { where("LENGTH(title) > ?", length) }
end

Scope vs Class 方法

Scopes 沒有做任何很厲害的事。就只是一個方法。其實也可以用類別方法做一樣的事情,像是:

class Fruit
  def self.with_juice
    where("juice > 0")    
  end
end

但是在這使用 scopes 而不使用類別方法有設計的優點。這是因為:

  • Scopes 因為語法上的關係,閱讀性比較高
  • Scopes 通常只做一件事,閱讀性比較高
  • Scopes 不會混和其他方法,閱讀性比較高

在功能性來說,唯一的差別是 scopes 保證一個 ActiveRecord::Relation ,但是類別方法不是。這樣當 scope 沒有回傳任何東西可以避免許多錯誤。

不要使用預設 Scopes

一個預設的 scope 會自動在 model 裡運作

class Post
  default_scope { where(published: true) }
end

預設 scopes 很迷人,但是通常會因為忘記有定義過導致有不如預期的結果,跳出奇怪的錯誤,浪費時間 debugger。


上一篇
<Day 29>加油好嗎?撰寫自己的類別
系列文
今晚我想來點 Ruby on Rails 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jrnalts
iT邦新手 5 級 ‧ 2020-10-08 00:26:23

恭喜完賽!
debugger表示:是你浪費我的時間

我要留言

立即登入留言